#include <iostream>
#include <vector>
#include <string>
#include<cstring>
#include <pthread.h>
#include <unistd.h>
using namespace std;

#define NUM 3

// int g_val = 0;

//__thread int g_val = 0;
// __thread int pid;
// __thread pthread_t tid;

// int *p = nullptr;

class threadData
{
public:
    threadData(int number)
    {
        _threadName = "thread-" + to_string(number);
    }

    string _threadName;
};

//__thread threadData;

string ToHex(pthread_t tid)
{
    char buff[128];
    snprintf(buff, sizeof(buff), "%p", tid);
    return buff;
}

void *Routine(void *args)
{
    pthread_detach(pthread_self());
    int test_i = 0;
    threadData *td = static_cast<threadData *>(args);
    // pid = getpid();
    // tid = pthread_self();
    //if(td->_threadName == "thread-2")   p = &test_i;
    for (int i = 0; i < 10; ++i)
    {
        // cout << td->_threadName << " is running, pid: " << getpid() << endl;

        cout << td->_threadName << ", test_i: " << test_i << ", &test_i: " << &test_i << endl;
        ++test_i;

        // cout << td->_threadName << ", g_val: " << g_val++ << ", &g_val: " << &g_val << endl;

        //cout << td->_threadName << ", pid: " << pid << ", tid: " << ToHex(tid) << endl;

        sleep(1);
    }
    // cout << td->_threadName << " quit" << endl;
    return nullptr;
}

int main()
{
    vector<pthread_t> tids;
    vector<threadData *> tds;
    for (int i = 0; i < NUM; ++i)
    {
        pthread_t tid;
        threadData *td = new threadData(i);
        tds.push_back(td);
        pthread_create(&tid, nullptr, Routine, td);
        tids.push_back(tid);
        sleep(1);
    }
    //sleep(1);
    //cout << "main thread get a thread's local value: " << *p << ", &value: " << p << endl;
    
    // for (auto &tid : tids)
    // {
    //     pthread_join(tid, nullptr);
    // }

    for (int i = 0; i < tids.size(); ++i)
    {
        int ret = pthread_join(tids[i], nullptr);
        cout << tds[i]->_threadName << ", wait over, ret: " << ret << ", reason: " << strerror(ret) << endl;
    }

    for (auto &td : tds)
    {
        delete td;
    }

    return 0;
}




// int tickets = 1000;

// class threadData
// {
// public:
//     threadData(int number)
//     {
//         _threadName = "thread-" + to_string(number);
//     }

//     string _threadName;
// };

// void *Routine(void *args)
// {
//     threadData *td = static_cast<threadData*>(args);
//     while(true)
//     {
//         if(tickets > 0)
//         {
//             usleep(1000);
//             cout << td->_threadName << ", get a ticket, tickets: " << tickets << endl;
//             --tickets;
//         }
//         else break;
//     }
//     cout << td->_threadName << " quit" << endl;
//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     vector<threadData*> tds;
//     for(int i = 0; i < NUM; ++i)
//     {
//         pthread_t tid;
//         threadData *td = new threadData(i);
//         tds.push_back(td);
//         pthread_create(&tid, nullptr, Routine, td);
//         tids.push_back(tid);
//         //sleep(1);     //此处不能sleep，否则将无法看到Routine循环出现负数的情况
//     }
//     for(auto tid : tids)
//     {
//         pthread_join(tid, nullptr);
//     }
//     for(auto td : tds)
//     {
//         delete td;
//     }

//     return 0;
// }